import React from 'react';
import ReactDOM from 'react-dom';

import { getContainer } from './portalUtils';

class Portal extends React.Component {
    static displayName = 'Portal';
    componentDidMount() {
        this._isMounted = true;
        this._renderOverlay();
    }

    componentDidUpdate() {
        this._renderOverlay();
    }

    componentWillReceiveProps(nextProps) {
        if (
            this._overlayTarget &&
            nextProps.container !== this.props.container
        ) {
            this._portalContainerNode.removeChild(this._overlayTarget);
            this._portalContainerNode = getContainer(
                nextProps.container,
                document.body
            );
            this._portalContainerNode.appendChild(this._overlayTarget);
        }
    }

    componentWillUnmount() {
        this._isMounted = false;
        this._unrenderOverlay();
        this._unmountOverlayTarget();
    }

    _mountOverlayTarget = () => {
        if (!this._overlayTarget) {
            this._overlayTarget = document.createElement('div');
            this._portalContainerNode = getContainer(
                this.props.container,
                document.body
            );
            this._portalContainerNode.appendChild(this._overlayTarget);
        }
    };

    _unmountOverlayTarget = () => {
        if (this._overlayTarget) {
            this._portalContainerNode.removeChild(this._overlayTarget);
            this._overlayTarget = null;
        }
        this._portalContainerNode = null;
    };

    _renderOverlay = () => {
        let overlay = !this.props.children
            ? null
            : React.Children.only(this.props.children);

        // Save reference for future access.
        if (overlay !== null) {
            this._mountOverlayTarget();

            const initialRender = !this._overlayInstance;

            this._overlayInstance = ReactDOM.unstable_renderSubtreeIntoContainer(
                this,
                overlay,
                this._overlayTarget,
                () => {
                    if (initialRender && this.props.onRendered) {
                        this.props.onRendered();
                    }
                }
            );
        } else {
            // Unrender if the component is null for transitions to null
            this._unrenderOverlay();
            this._unmountOverlayTarget();
        }
    };

    _unrenderOverlay = () => {
        if (this._overlayTarget) {
            ReactDOM.unmountComponentAtNode(this._overlayTarget);
            this._overlayInstance = null;
        }
    };

    render() {
        return null;
    }

    getMountNode = () => {
        return this._overlayTarget;
    };
}

export default Portal;
